<?php namespace sacvoyage;

/*
 * document comparator, based on path values
 */
class Comparator {



	/*
	 * for example, to construct comparator that can sort by _id then by _rev:
	 * 
	 * new Comparator(array(
	 *   array('path': '$._id',  'order': 'asc'),
	 *   array('path': '$._rev', 'order': 'asc')
	 * ));
	 *
	 */
	public function __construct($orders=null) {
		$this->_orders=$orders;
	}

	/*
	 * returns 1 if $doc1>$doc2, -1 if $doc1<$doc2, 0 if $doc1==$doc2 
	 */
	public function compare($obj1, $obj2) {
		$finder1=new Pathfinder(clone $obj1);
		$finder2=new Pathfinder(clone $obj2);
		
		// if orders not set, objects' all keys are orders
		if($this->_orders) {
			$orders=$this->_orders;
		} else {
			$paths=array_keys(array_merge(
				$finder1->get(), 
				$finder2->get()
			));
			sort($paths);
			$orders=array();
			foreach($paths as $path) {
				$orders[]=array('path'=>$path, 'order'=>'desc');
			}
		}
		
		
		foreach($orders as $order) {
			try { $val1=$finder1[$order['path']]; } catch (Exception $e) { $val1=null; }
			try { $val2=$finder2[$order['path']]; } catch (Exception $e) { $val2=null; }
			
			if(($cmp=$this->_compareValues($val1, $val2, $order['order']))!=0) {
				return $cmp;
			}
			// if equal, go to next path
		}
		return 0; // if all paths' values equal

	
		// if all equal, than equal
		return 0;
	}
	
	private $_order;
	
	private function _compareValues($val1, $val2, $order='asc') {
		$order=($order!='desc') ? 1 : -1;
		if(is_null($val1)) { // null is always bigger, unless other is null
			return !is_null($val2) ? -$order : 0;
		}
		if(is_null($val2)) {
			return !is_null($val1) ? $order : 0;
		}
		if($val1>$val2) {
			return -$order;
		} elseif ($val1<$val2) {
			return $order;
		} else {
			return 0;
		}
	}

}

?>
